package com.crm.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crm.crm.constant.CacheConstant;
import com.crm.crm.domain.*;
import com.crm.crm.domain.dto.AssignmentDto;
import com.crm.crm.domain.dto.PageQueryParams;
import com.crm.crm.domain.dto.business.FalseCluesReportDto;
import com.crm.crm.domain.dto.business.RecordDto;
import com.crm.crm.domain.vo.ClueVo;
import com.crm.crm.domain.vo.PageResult;
//import com.crm.crm.mapper.Clue1Mapper;
import com.crm.crm.domain.vo.SeriesData;
import com.crm.crm.domain.vo.contract.ContractReportResponse;
import com.crm.crm.mapper.*;
import com.crm.crm.service.CluePoolService;
import com.crm.crm.service.ClueService;
import com.crm.crm.service.RecordService;
import com.crm.crm.service.UserService;
import com.crm.crm.util.GetDateRange;
import com.crm.crm.util.UserThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.crm.crm.constant.CacheConstant.STATUS_TRACKING;

@Service
@Slf4j
public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements ClueService {
    @Autowired
    private ClueMapper clueMapper;

    @Autowired
    private RecordService recordService;
    @Autowired
    private RecordMapper recordMapper;
    @Autowired
    private CluePoolService cluePoolService;
    @Autowired
    private BusinessMapper businessMapper;
    @Autowired
    private CluePoolMapper cluePoolMapper;
    @Autowired
    private ActivityMapper activityMapper;
    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private RulePoolMapper rulePoolMapper;
    @Autowired
    private IndexMapper indexMapper;

    public static final String STATUS_BABY = "3";

    //新增线索
    @Override


    public String add(Clue clue) {
        String currentUserName = UserThreadLocalUtil.getCurrentUserName();

        //判断当前用户持有数是否超过最大可持有数
        Integer maxNumber = getMaxNumber();

        LambdaQueryWrapper<Clue> userWrapper = new LambdaQueryWrapper<Clue>().eq(Clue::getOwner, currentUserName);
        List<Clue> businessOpportunities = clueMapper.selectList(userWrapper);
        if (businessOpportunities.size() < maxNumber) {
            clue.setCreateBy(currentUserName);
            clue.setUpdateBy(currentUserName);
            clue.setCreateTime(LocalDateTime.now());
            clue.setUpdateTime(LocalDateTime.now());
            clue.setOwner(currentUserName);
            clue.setStatus("1");
            clue.setOwnerTime(LocalDateTime.now());
            Activity activity = activityMapper.selectById(clue.getActivityId());
            clue.setActivityName(activity.getName());
            clue.setActivityInfo(activity.getInfo());
            clueMapper.insert(clue);
            //新增记录
            String createBy = clue.getCreateBy();
            LambdaQueryWrapper<InsertRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BeanUtil.isNotEmpty(createBy),InsertRecord::getCreateBy,createBy);
            InsertRecord insertRecord = indexMapper.selectOne(wrapper);
            if(insertRecord == null){
                InsertRecord insertRecordNew = new InsertRecord();
                BeanUtil.copyProperties(clue,insertRecordNew);
                insertRecordNew.setClueCount(1); // 设置线索增加数
                insertRecordNew.setClueChangeCount(0); // 设置线索转化数
                insertRecordNew.setBusinessCount(0); // 设置商机增加数
                insertRecordNew.setBusinessChangeCount(0); // 设置商机转化数
                indexMapper.insert(insertRecordNew);
            }else {
                insertRecord.setBusinessCount(insertRecord.getClueCount()+1);
            }
            return null;
        }
        return "当前用户线索数已满";
    }

    /**
     * 获取最大可持有数
     *
     * @return
     */
    public Integer getMaxNumber() {
        LambdaQueryWrapper<RulePool> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RulePool::getType, "0");
        RulePool rulePool = rulePoolMapper.selectOne(wrapper);
        return rulePool.getMaxNunmber();
    }


    /*线索分页查询*/

    @Override
    public PageResult<Clue> pageQuery(PageQueryParams pageQueryParams) {
        Page<Clue> page = new Page<>(pageQueryParams.getPageNum(), pageQueryParams.getPageSize());


        LambdaQueryWrapper<Clue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotEmpty(pageQueryParams.getId()), Clue::getId, pageQueryParams.getId());
        queryWrapper.like(pageQueryParams.getPhone() != null, Clue::getPhone, pageQueryParams.getPhone());
        queryWrapper.like(StringUtils.isNotEmpty(pageQueryParams.getOwner()), Clue::getCreateBy, pageQueryParams.getOwner());
        queryWrapper.eq(pageQueryParams.getStatus() != null, Clue::getStatus, pageQueryParams.getStatus());

        if (StringUtils.isNotEmpty(pageQueryParams.getBeginCreateTime()) && StringUtils.isNotEmpty(pageQueryParams.getEndCreateTime())) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate beginCreatTime = LocalDate.parse(pageQueryParams.getBeginCreateTime(), formatter);
            LocalDate endCreatTime = LocalDate.parse(pageQueryParams.getEndCreateTime(), formatter);
            queryWrapper.between(Clue::getCreateTime, beginCreatTime, endCreatTime);
        }
        Page<Clue> result = clueMapper.selectPage(page, queryWrapper);

        return new PageResult<>(result.getTotal(), result.getRecords());
    }

    /*线索根据id查看详情*/
    @Override
    public ClueVo getById(Integer id) {
        Clue clue = clueMapper.selectOne(Wrappers.<Clue>lambdaQuery().eq(Clue::getId, id));
        ClueVo clueVo = new ClueVo();
        if (clue != null) {

            BeanUtil.copyProperties(clue, clueVo);
            return clueVo;
        } else if (clue == null) {
            CluePool cluePool = cluePoolService.getOne(Wrappers.<CluePool>lambdaQuery().eq(CluePool::getId, id));
            BeanUtil.copyProperties(cluePool, clueVo);
            return clueVo;
        }
        return null;
    }

    /*跟踪记录回显*/
    @Override
    public PageResult<RecordOne> getRecordList(Integer id) {

        List<RecordOne> recordList = recordMapper.selectRecord(id);

        return new PageResult<>(Long.valueOf(recordList.size()), recordList);
    }

    @Override
    public void saveClues(List<Clue> resultDataList) {
        for (Clue clue : resultDataList) {
            clue.setCreateBy(UserThreadLocalUtil.getCurrentUserName());
            clue.setUpdateBy(UserThreadLocalUtil.getCurrentUserName());
            clue.setCreateTime(LocalDateTime.now());
            clue.setUpdateTime(LocalDateTime.now());
            clue.setOwner(UserThreadLocalUtil.getCurrentUserName());
            clue.setStatus("1");
            clueMapper.insert(clue);
        }
    }

    /*新增跟进*/
    @Override
    public void addRecord(RecordDto recordDto) {
        RecordOne recordOne = new RecordOne();
        BeanUtil.copyProperties(recordDto, recordOne);
        recordOne.setFalseReason(recordDto.getReason());
        recordOne.setCreateBy(UserThreadLocalUtil.getCurrentUserName());
        recordOne.setCreateTime(LocalDateTime.now());
        recordOne.setUpdateTime(LocalDateTime.now());
        recordOne.setUpdateBy(UserThreadLocalUtil.getCurrentUserName());
        clueMapper.addRecord(STATUS_TRACKING, Integer.valueOf(recordOne.getClueId()));
        recordMapper.insertRecord(recordOne);
        Clue clue = new Clue();
        clue.setId(Integer.valueOf(recordOne.getClueId()));
        BeanUtil.copyProperties(recordOne, clue);
        clueMapper.update(clue, Wrappers.<Clue>lambdaUpdate().eq(Clue::getId, recordOne.getClueId()));

    }

    //分配 与批量分配
    @Override
    public String assignment(AssignmentDto assignmentDto) {

        List<Integer> ids = assignmentDto.getIds();
        Long i = (long)ids.size();
        Integer userId = assignmentDto.getUserId();
        String owner = clueMapper.findUserId(userId);

        //判断分配后用户持有总数是否会大于最大可持有数
        Integer maxNumber = getMaxNumber();
        //判断加上size，用户总持有数是否大于最大可持有数
        LambdaQueryWrapper<Clue> userWrapper = new LambdaQueryWrapper<Clue>().eq(Clue::getOwner, owner);
        List<Clue> Clues = clueMapper.selectList(userWrapper);
        if (Clues.size() + ids.size() > maxNumber) {
            //throw new RuntimeException("捞取线索不能超过" + maxNumber + "条");
            return "修改后用户持有总数会大于最大可持有数";
        }

        clueMapper.setOwner(ids,owner);
        return null;

    }

    //pool分页查询
    @Override
    public PageResult<CluePool> poolQuery(PageQueryParams pageQueryParams) {
        Page<CluePool> page = new Page<>(pageQueryParams.getPageNum(), pageQueryParams.getPageSize());

        LambdaQueryWrapper<CluePool> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotEmpty(pageQueryParams.getId()), CluePool::getClueId, pageQueryParams.getId());
        queryWrapper.like(pageQueryParams.getPhone() != null, CluePool::getPhone, pageQueryParams.getPhone());
        queryWrapper.like(StringUtils.isNotEmpty(pageQueryParams.getOwner()), CluePool::getCreateBy, pageQueryParams.getOwner());
        queryWrapper.eq(pageQueryParams.getStatus() != null, CluePool::getStatus, pageQueryParams.getStatus());

        if (StringUtils.isNotEmpty(pageQueryParams.getBeginCreateTime()) && StringUtils.isNotEmpty(pageQueryParams.getEndCreateTime())) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate beginCreatTime = LocalDate.parse(pageQueryParams.getBeginCreateTime(), formatter);
            LocalDate endCreatTime = LocalDate.parse(pageQueryParams.getEndCreateTime(), formatter);
            queryWrapper.between(CluePool::getCreateTime, beginCreatTime, endCreatTime);
        }
        Page<CluePool> result = cluePoolService.page(page, queryWrapper);

        return new PageResult<>(result.getTotal(), result.getRecords());
    }
    //捞取
    @Override
    @Transactional
    public String gain(AssignmentDto gain) {
        List<Integer> ids = gain.getIds();
        if (ids.size() > 3) {
            //throw new RuntimeException("捞取线索不能超过3条");
            return "捞取线索不能超过3条";
        }

        String currentUserName = UserThreadLocalUtil.getCurrentUserName();
        //判断分配后用户持有总数是否会大于最大可持有数
        Integer maxNumber = getMaxNumber();
        //判断加上size，用户总持有数是否大于最大可持有数
        LambdaQueryWrapper<Clue> userWrapper = new LambdaQueryWrapper<Clue>().eq(Clue::getOwner, currentUserName);
        List<Clue> Clues = clueMapper.selectList(userWrapper);
        if (Clues.size() + ids.size() > maxNumber) {
            //throw new RuntimeException("捞取线索不能超过" + maxNumber + "条");
            return "捞取后当前用户持有总数会大于最大可持有数";
        }

        //redis查一下看看是否存在重复捞取限制的
        for (Integer id : ids) {
            String string = redisTemplate.opsForValue().get(CacheConstant.RECYCLE_LIMIT_CLUE + id);
            if (string != null) {
                //throw new RuntimeException("存在处于重复捞取时限内的数据");
                return "存在处于重复捞取时限内的数据";
            }
        }

        Integer userId = gain.getUserId();
        String owner = clueMapper.findUserId(userId);
        List<CluePool> cluePoools = cluePoolMapper.selectBatchIds(ids);

        final List<Clue> clues = cluePoools.stream().map(cluePool -> {
            Clue clue = new Clue();
            BeanUtil.copyProperties(cluePool, clue);
            clue.setStatus("1");
            clue.setOwner(owner);
            return clue;
        }).collect(Collectors.toList());
        for (Clue clue : clues) {
            clueMapper.insert(clue);
            //添加重复捞取限制
            addRecycleLimit(clue);
        }
        cluePoolMapper.deleteByIds(ids);
        return null;
    }

    /*添加重复捞取限制方法*/
    private void addRecycleLimit(Clue clue) {
        int id = clue.getId();
        //拿限制时间与格式
        LambdaQueryWrapper<RulePool> wrapper = new LambdaQueryWrapper<RulePool>().eq(RulePool::getType, "0");
        RulePool rulePool = rulePoolMapper.selectOne(wrapper);
        Integer repeatGetTime = rulePool.getRepeatGetTime();
        String repeatType = rulePool.getRepeatType();
        switch (repeatType) {
            case "1":
                //时间类型为天
                redisTemplate.opsForValue().set(CacheConstant.RECYCLE_LIMIT_CLUE + id, "1", repeatGetTime, TimeUnit.DAYS);
                break;
            case "2":
                //时间类型为周
                redisTemplate.opsForValue().set(CacheConstant.RECYCLE_LIMIT_CLUE + id, "1", (repeatGetTime * 7), TimeUnit.DAYS);
                break;
            case "3":
                //时间类型为月
                redisTemplate.opsForValue().set(CacheConstant.RECYCLE_LIMIT_CLUE + id, "1", (repeatGetTime * 30), TimeUnit.DAYS);
                break;
            default:
                log.info("时间类型错误,请检查数据库或数据字典");
        }
    }


    /*为线索上报*/
    @Override
    @Transactional
    public void falseClue(FalseCluesReportDto falseCluesReportDto) {
        Clue clue = clueMapper.selectOne(Wrappers.<Clue>lambdaQuery().eq(Clue::getId, falseCluesReportDto.getId()));
        if (clue == null) {
            return;
        }
        Integer falseCount = clue.getFalseCount();
        clue.setFalseCount(falseCount + 1);
        if (clue.getFalseCount() >= 3) {
            log.info("为线索上报次数>=3次删除线索");
            clueMapper.delete(Wrappers.<Clue>lambdaQuery().eq(Clue::getId, falseCluesReportDto.getId()));
            return;
        }
        RecordOne recordOne = new RecordOne();
        BeanUtil.copyProperties(clue, recordOne);
        recordOne.setFalseReason(falseCluesReportDto.getReason());
        recordOne.setCreateBy("admin");
        recordOne.setCreateTime(LocalDateTime.now());
        recordOne.setUpdateTime(LocalDateTime.now());
        recordOne.setUpdateBy("admin");
        recordMapper.insertRecord(recordOne);

        CluePool cluePool = new CluePool();
        BeanUtil.copyProperties(clue, cluePool);
        cluePool.setReason(falseCluesReportDto.getReason());
        cluePool.setRemark(falseCluesReportDto.getRemark());
        cluePool.setCreateTime(LocalDateTime.now());
        log.info("为线索上报次数<3次,线索转移到线索池");
        cluePoolService.save(cluePool);
        clueMapper.delete(Wrappers.<Clue>lambdaQuery().eq(Clue::getId, falseCluesReportDto.getId()));






    }

    /*线索转商机*/
    @Override
    @Transactional
    public void changeBusiness(Integer id) {
        Clue clue = clueMapper.selectOne(Wrappers.<Clue>lambdaQuery().eq(Clue::getId, id));
        if (clue == null) {
            return;
        }
        BusinessOpportunity businessOpportunity = new BusinessOpportunity();
        BeanUtil.copyProperties(clue, businessOpportunity);
        log.info("线索转商机");
        businessMapper.insert(businessOpportunity);
        //新增记录
        String createBy = clue.getCreateBy();
        LambdaQueryWrapper<InsertRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BeanUtil.isNotEmpty(createBy),InsertRecord::getCreateBy,createBy);
        InsertRecord insertRecord = indexMapper.selectOne(wrapper);
        if(insertRecord == null){
            throw new RuntimeException("新增记录失败");
        }else {
            insertRecord.setBusinessCount(insertRecord.getClueChangeCount()+1);
            insertRecord.setBusinessChangeCount(insertRecord.getBusinessCount()+1);
        }
        clueMapper.delete(Wrappers.<Clue>lambdaQuery().eq(Clue::getId, id));
//        clueMapper.delete(Wrappers.<Clue>lambdaQuery().eq(Clue::getId, id));


    }
    //查询线索数量
    @Override
    public Long selectOwner(String userName) {
        Long l = clueMapper.selectClueNum(userName);
        Long l1= clueMapper.selectCluePoolNum(userName);
        Long s =l+l1;
        return s;
    }


    //统计新增线索和线索总数
    @Override
    public ContractReportResponse cluesStatistics(String beginCreateTime, String endCreateTime) {
        //  获取时间范围内所有日期
        List<String> dates = GetDateRange.generateDateRange(beginCreateTime, endCreateTime);

        // 查询时间范围内的所有线索记录
        List<Clue> clues = getCluesInDateRange(beginCreateTime, endCreateTime);

        //  构建每天的新增线索数
        List<Integer> newClues = new ArrayList<>();
        for (String date : dates) {
            int count = countCluesOnDay(clues, date);
            newClues.add(count);
        }

        // 构建每天的累计线索数（从第1天开始累加）
        List<Integer> totalClues = new ArrayList<>();
        int cumulativeCount = 0;
        for (Integer dailyCount : newClues) {
            cumulativeCount += dailyCount;
            totalClues.add(cumulativeCount);
        }

        //  构造响应对象
        ContractReportResponse response = new ContractReportResponse();
        SeriesData newData = new SeriesData();
        SeriesData totalData = new SeriesData();

        newData.setName("新增线索数量");
        newData.setData(newClues);

        totalData.setName("线索总数量");
        totalData.setData(totalClues);

        response.setXAxis(dates);
        response.setSeries(List.of(newData, totalData));

        return response;
    }


    //查询指定时间范围内的所有线索
    private List<Clue> getCluesInDateRange(String beginTime, String endTime) {
        //使用lambdaQuery构建查询条件，查询createTime在指定时间范围内的线索
        return clueMapper.selectList(Wrappers.<Clue>lambdaQuery()
                //查询createTime大于等于beginTime的线索
                .ge(Clue::getCreateTime, beginTime)
                //查询createTime小于等于endTime的线索
                .le(Clue::getCreateTime, endTime + " 23:59:59"));
    }


    //按天统计线索数
    private int countCluesOnDay(List<Clue> clues, String dateStr) {
        //使用流式处理，过滤出创建时间在指定日期的线索
        return (int) clues.stream()
                //过滤出创建时间不为空的线索
                .filter(clue -> {
                    if (clue.getCreateTime() == null) return false;

                    //将线索的创建时间转换为LocalDate类型
                    LocalDate clueDate = clue.getCreateTime().toLocalDate();
                    //将指定日期字符串转换为LocalDate类型
                    LocalDate targetDate = LocalDate.parse(dateStr);

                    //判断线索的创建时间是否在指定日期的范围内
                    return !clueDate.isBefore(targetDate) && !clueDate.isAfter(targetDate);
                })
                //统计符合条件的线索数量
                .count();
    }


}
